package com.chen.common;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Date;
import java.util.Locale;

import lombok.extern.slf4j.Slf4j;

/**
 * 项目--项目跟踪日志
 *
 * @author 陈彭伟
 * @since 2021-08-21 19:03:50
 */
@Slf4j
public class Dates {
	private Dates() {
	}

	//针对"Oct 1, 1959 12:00:00 AM"的格式,必须设置"Locale.ENGLISH",否则无法解析
	public static final DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
			.appendOptional(DateTimeFormatter.ofPattern("MMM d, yyyy K:m:s a"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy-M-dd"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy/MM/dd"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyy/M/dd"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyyMMddHHmmss.SSS"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyyMMddHHmm"))
			.appendOptional(DateTimeFormatter.ofPattern("yyyyMMdd"))
			.appendOptional(DateTimeFormatter.ofPattern("HH:mm:ss"))
			.appendOptional(DateTimeFormatter.ofPattern("HHmmss"))
			.toFormatter(Locale.ENGLISH);

	public static LocalDateTime asLocalDateTime(String string) {
		try {
			return LocalDateTime.parse(string, dateTimeFormatter);
		} catch (Exception e) {
			log.error("{} asLocalDateTime error ", string, e);
		}
		return null;
	}

	public static LocalDateTime asLocalDateTime(String string, String format) {
		try {
			return LocalDateTime.parse(string, DateTimeFormatter.ofPattern(format));
		} catch (Exception e) {
			log.error("{} asLocalDateTime error ", string, e);
		}
		return null;
	}

	public static LocalDateTime asLocalDateTime(Date date) {
		try {
			return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
		} catch (Exception e) {
			log.error("Date asLocalDateTime error ", e);
		}
		return null;
	}

	public static LocalDate asLocalDate(String string) {
		try {
			return LocalDate.parse(string, dateTimeFormatter);
		} catch (Exception e) {
			log.error("{} asLocalDate error ", string, e);
		}
		return null;
	}

	public static LocalDate asLocalDate(String string, String format) {
		try {
			return LocalDate.parse(string, DateTimeFormatter.ofPattern(format));
		} catch (Exception e) {
			log.error("{} asLocalDate error ", string, e);
		}
		return null;
	}

	public static LocalDate asLocalDate(Date date) {
		try {
			return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
		} catch (Exception e) {
			log.error("Date asLocalDate error ", e);
		}
		return null;
	}

	public static LocalTime asLocalTime(String string) {
		try {
			return LocalTime.parse(string, dateTimeFormatter);
		} catch (Exception e) {
			log.error("{} asLocalTime error ", string, e);
		}
		return null;
	}

	public static LocalTime asLocalTime(String string, String format) {
		try {
			return LocalTime.parse(string, DateTimeFormatter.ofPattern(format));
		} catch (Exception e) {
			log.error("{} asLocalTime error ", string, e);
		}
		return null;
	}

	public static LocalTime asLocalTime(Date date) {
		try {
			return date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
		} catch (Exception e) {
			log.error("Date asLocalTime error ", e);
		}
		return null;
	}

	public static Date asDate(LocalDateTime localDateTime) {
		try {
			return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
		} catch (Exception e) {
			log.error("LocalDateTime asLocalTime error ", e);
		}
		return null;
	}

	public static Date asDate(LocalDate localDate) {
		try {
			ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
			return Date.from(zonedDateTime.toInstant());
		} catch (Exception e) {
			log.error("LocalDate asLocalTime error ", e);
		}
		return null;
	}

	public static Date asDate(String date, String format) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			return sdf.parse(date);
		} catch (Exception e) {
			log.error("{} asDate error ", date, e);
		}
		return null;
	}

	public static Date asDate(String date) {
		LocalDateTime localDateTime = asLocalDateTime(date);
		if (localDateTime != null) {
			return asDate(localDateTime);
		}
		LocalDate localDate = asLocalDate(date);
		if (localDate != null) {
			return asDate(localDate);
		}
		return null;
	}

	public static String asString(LocalDateTime localDateTime, String format) {
		try {
			return localDateTime.format(DateTimeFormatter.ofPattern(format));
		} catch (Exception e) {
			log.error("LocalDateTime asString error ", e);
		}
		return null;
	}

	public static String asString(LocalDate localDate, String format) {
		try {
			return localDate.format(DateTimeFormatter.ofPattern(format));
		} catch (Exception e) {
			log.error("LocalDate asString error ", e);
		}
		return null;
	}

	public static String asString(LocalTime localTime, String format) {
		try {
			return localTime.format(DateTimeFormatter.ofPattern(format));
		} catch (Exception e) {
			log.error("LocalTime asString error ", e);
		}
		return null;
	}

	public static String asString(Date date, String format) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			return sdf.format(date);
		} catch (Exception e) {
			log.error("Date asString error ", e);
		}
		return null;
	}
}
